/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhike
 * date:2016年5月1日
 *
 */
package com.acooly.module.openapi.client.provider.sinapay.message.trade;

import com.acooly.core.utils.Ids;
import com.acooly.core.utils.Money;
import com.acooly.core.utils.Strings;
import com.acooly.core.utils.validate.jsr303.MoneyConstraint;
import com.acooly.module.openapi.client.api.anotation.ApiItem;
import com.acooly.module.openapi.client.api.enums.ApiMessageType;
import com.acooly.module.openapi.client.api.exception.ApiMessageCheckException;
import com.acooly.module.openapi.client.provider.sinapay.annotation.ApiTransient;
import com.acooly.module.openapi.client.provider.sinapay.annotation.SinaGateWay;
import com.acooly.module.openapi.client.provider.sinapay.domain.SinapayApiMsg;
import com.acooly.module.openapi.client.provider.sinapay.domain.SinapayRequest;
import com.acooly.module.openapi.client.provider.sinapay.enums.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.NotEmpty;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

/**
 * @author zhike
 */
@Getter
@Setter
@SinaGateWay(SinapayGateWayType.PAYMENT)
@SinapayApiMsg(service = SinapayServiceNameEnum.CREATE_HOSTING_DEPOSIT, type = ApiMessageType.Request)
public class CreateHostingDepositRequest extends SinapayRequest {

	/**
	 * 交易订单号
	 *
	 * 商户网站交易订单号，商户内部保证唯一
	 */
	@NotEmpty
	@Size(max = 32)
	@ApiItem(value = "out_trade_no")
	private String outTradeNo = Ids.oid();

	/**
	 * 摘要
	 *
	 * 充值内容摘要
	 */
	@Size(max = 64)
	@ApiItem(value = "summary")
	private String summary;

	/**
	 * 用户标识信息
	 *
	 * 商户系统用户ID(字母或数字)
	 */
	@NotEmpty
	@Size(max = 50)
	@ApiItem(value = "identity_id")
	private String identityId;

	/**
	 * 用户标识类型
	 *
	 * ID的类型，参考“标志类型”
	 */
	@NotEmpty
	@Size(max = 16)
	@ApiItem(value = "identity_type")
	private String identityType = "UID";

	/**
	 * 账户类型
	 *
	 * 账户类型（基本户、保证金户,存钱罐、银行账户）。默认基本户，见附录
	 */
	@Size(max = 16)
	@ApiItem(value = "account_type")
	private String accountType = SinapayAccountType.SAVING_POT.code();

	/**
	 * 金额
	 *
	 * 单位为：RMB Yuan。精确到小数点后两位。
	 */
	@MoneyConstraint
	@ApiItem(value = "amount")
	private Money amount;

	/**
	 * 用户手续费
	 *
	 * 用户承担的手续费金额
	 */
	@MoneyConstraint(nullable = true)
	@ApiItem(value = "user_fee")
	private Money userFee;

	/**
	 * 付款用户IP地址
	 *
	 * 用户在商户平台发起支付时候的IP地址，公网IP，不是内网IP，用于风控校验，请填写用户真实IP，否则容易风控拦截
	 */
	@NotEmpty
	@Size(max = 32)
	@ApiItem(value = "payer_ip")
	private String payerIp;

	/**
	 * 充值关闭时间
	 *
	 * 设置未付款交易的超时时间，一旦超时，该笔交易就会自动被关闭。
	 * 取值范围：15m～15h。 m-分钟，h-小时 不接受小数点
	 */
	@Size(max = 8)
	@ApiItem(value = "deposit_close_time")
	private String depositCloseTime;

	/**
	 * 支付方式
	 *
	 * 格式：支付方式^金额^扩展|支付方式^金额^扩展。扩展信息内容以“，”分隔，针对不同支付方式的扩展定义见附录 “支付方式扩展”
	 * 另：支付方式：线下支付需接口1.1版本才支持，且仅支持企业用户
	 */
	@Size(max = 1000)
	@ApiItem(value = "pay_method")
	private String payMethod;

	/**
	 * 收银台地址类别
	 *
	 * 收银台地址类型，目前只包含MOBILE。为空时默认返回PC版页面，当传值为“MOBILE”时返回移动版页面。
	 */
	@Size(max = 10)
	@ApiItem(value = "cashdesk_addr_category")
	private String cashdeskAddrCategory;

	/**
	 * 新浪支付方式
	 */
	@NotNull
	@ApiTransient
	private SinapayMode payMode = SinapayMode.ONLINE_BANK;
	@ApiTransient
	private SinapayBankCode bankCode;
	@ApiTransient
	private SinapayCardType cardType = SinapayCardType.DEBIT;
	/** 卡属性 */
	@ApiTransient
	private SinapayCardAttribute cardAttribute = SinapayCardAttribute.C;
	/** 绑卡ID */
	@ApiTransient
	private String cardId;

	public CreateHostingDepositRequest() {
		super();
	}

	/**
	 * 网银方式
	 * 
	 * @param identityId
	 * @param amount
	 * @param payerIp
	 * @param bankCode
	 * @param cardType
	 * @param cardAttribute
	 */
	public CreateHostingDepositRequest(String identityId, Money amount, String payerIp, SinapayBankCode bankCode,
			SinapayCardType cardType, SinapayCardAttribute cardAttribute) {
		this();
		this.identityId = identityId;
		this.amount = amount;
		this.payerIp = payerIp;
		this.bankCode = bankCode;
		this.cardType = cardType;
		this.cardAttribute = cardAttribute;
	}

	/**
	 * 绑卡方式
	 * 
	 * @param identityId
	 * @param amount
	 * @param payerIp
	 * @param cardId
	 */
	public CreateHostingDepositRequest(String identityId, Money amount, String payerIp, String cardId) {
		this();
		this.payMode = SinapayMode.BINDING_PAY;
		this.identityId = identityId;
		this.amount = amount;
		this.payerIp = payerIp;
		this.cardId = cardId;
	}

	@Override
	public void doCheck() throws ApiMessageCheckException {
		super.doCheck();
		if (payMode == SinapayMode.ONLINE_BANK) {
			if (bankCode == null || cardType == null || cardAttribute == null) {
				throw new ApiMessageCheckException("网银方式bankCode,cardType和cardAttribute都是必须的");
			}
		} else if (payMode == SinapayMode.BINDING_PAY) {
			if (Strings.isBlank(cardId)) {
				throw new ApiMessageCheckException("绑卡方式cardId是必须的");
			}
		} else {
			throw new ApiMessageCheckException("暂时只支持网银和绑卡两种方式");
		}
	}

	public String getPayMethod() {
		if (Strings.isBlank(payMethod)) {
			StringBuilder sb = new StringBuilder();
			if (payMode == SinapayMode.ONLINE_BANK) {
				// 网银
				sb.append(payMode.code()).append("^").append(this.amount.toString()).append("^").append(this.bankCode.code())
						.append(",").append(this.cardType.code()).append(",").append(this.cardAttribute.code());
			} else if (payMode == SinapayMode.BINDING_PAY) {
				// 绑卡
				sb.append(payMode.code()).append("^").append(this.amount.toString()).append("^").append(this.cardId);
			}
			this.payMethod = sb.toString();
		}
		return payMethod;
	}
}
